* xterm.h: New section for declarations for xfaces.c.
authorJim Blandy <jimb@redhat.com>
Tue, 25 May 1993 14:02:58 +0000 (14:02 +0000)
committerJim Blandy <jimb@redhat.com>
Tue, 25 May 1993 14:02:58 +0000 (14:02 +0000)
(init_frame_faces, free_frame_faces, intern_face,
face_name_id_number, same_size_fonts, recompute_basic_faces,
compute_char_face, compute_glyph_face): Declare these here.
* xfaces.c (same_size_fonts): We can now remove this extern
declaration.
* xfns.c (face_name_id_number): Likewise.
* xterm.c (intern_face): Likewise.

* xfaces.c (build_face, unload_font, free_frame_faces): Don't
forget to block input while making X calls.

Treat faces as structures specifying modifications to the frame's
parameters, rather than things which need to specify a complete
set of parameters by themselves.
* xfaces.c (init_frame_faces): Don't set up the two frame display
faces by querying the GC - just leave all their fields blank, and
call recompute_basic_faces, letting build_face do the work of
consulting the frame when necessary.
(recompute_basic_faces): New function.
(compute_base_faces): New function for obtaining the "identity"
for compute_char_face and compute_glyph_face.
(compute_char_face, compute_glyph_face): Call it, instead of copying
FRAME_DEFAULT_FACE.
* xfns.c (x_make_gc): No need to call init_frame_faces here.

* xfaces.c (intern_frame_face): This can be static.

* dispextern.h (struct face): New field - `copy', to help us with
resource allocation.
* xfaces.c (free_frame_faces): Do free the first two faces; don't
free anything from a face that's a copy.
(intern_frame_face): Mark every face we intern as a copy; its
resources are actually a combination of the real faces.
(Fset_face_attribute_internal): No need to check if we're trying
to free one of the frame's GC's; they never enter into the
picture.

* xfns.c (Fx_list_fonts): New function.
(face_name_id_number): Add extern declaration for this.
* xfaces.c (face_name_id_number): Make this externally visible,
and make the FRAME argument a FRAME_PTR, not a Lisp_Object.
(compute_char_face): Call face_name_id_number properly.

src/xfaces.c

index 9b301e35b79c73cec02cee5cf5ef49d4913b319b..0c72456b141f34606adc0f9fb6ca654b0de71fb1 100644 (file)
@@ -61,6 +61,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
            use right now, and
        UNDERLINE-P is non-nil if the face should be underlined.
+   If any of these elements are nil, that allows the frame's parameters to
+   show through.
    (lisp/faces.el maintains these association lists.)
 
    The frames' private alists hold the frame-local definitions for the
@@ -136,10 +138,6 @@ int next_face_id;
 /* The number of the face to use to indicate the region.  */
 int region_face;
 
-/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
-   We assume that they're both character-cell fonts.  */
-extern int same_size_fonts ();
-
 /* This is what appears in a slot in a face to signify that the face
    does not specify that display aspect.  */
 #define FACE_DEFAULT (~0)
@@ -318,27 +316,37 @@ build_face (f, face)
   XGCValues xgcv;
   unsigned long mask;
 
+  BLOCK_INPUT;
+
   if (face->foreground != FACE_DEFAULT)
     xgcv.foreground = face->foreground;
   else
-    xgcv. foreground = f->display.x->foreground_pixel;
+    xgcv.foreground = f->display.x->foreground_pixel;
+
   if (face->background != FACE_DEFAULT)
     xgcv.background = face->background;
   else
-    xgcv. background = f->display.x->background_pixel;
+    xgcv.background = f->display.x->background_pixel;
+
   if (face->font && (int) face->font != FACE_DEFAULT)
     xgcv.font = face->font->fid;
   else
     xgcv.font = f->display.x->font->fid;
+
   xgcv.graphics_exposures = 0;
+
   mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
   gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
                  mask, &xgcv);
+
 #if 0
   if (face->stipple && face->stipple != FACE_DEFAULT)
     XSetStipple (x_current_display, gc, face->stipple);
 #endif
+
   face->gc = gc;
+
+  UNBLOCK_INPUT;
 }
 
 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps.  */
@@ -371,7 +379,10 @@ unload_font (f, font)
 {
   if (!font || font == ((XFontStruct *) FACE_DEFAULT))
     return;
+
+  BLOCK_INPUT;
   XFreeFont (x_current_display, font);
+  UNBLOCK_INPUT;
 }
 
 static unsigned long
@@ -432,47 +443,17 @@ unload_color (f, pixel)
 \f
 /* Initializing face arrays for frames. */
 
-/* Set up faces 0 and 1 based on the normal text and modeline GC's.
-   This gets called whenever the parameters stored in the frame itself
-   (i.e. font, background color, etcetera) change.
-
-   Note that the first two faces just contain references to the
-   frame's own resources.  We shouldn't free them.  */
 void
 init_frame_faces (f)
-     struct frame *f;
+     FRAME_PTR f;
 {
   ensure_face_ready (f, 0);
-  {
-    XGCValues gcv;
-    struct face *face = FRAME_FACES (f) [0];
-
-    XGetGCValues (x_current_display, f->display.x->normal_gc,
-                 GCForeground | GCBackground | GCFont, &gcv);
-    face->gc         = f->display.x->normal_gc;
-    face->foreground = gcv.foreground;
-    face->background = gcv.background;
-    face->font       = f->display.x->font;
-    face->stipple = 0;
-    face->underline = 0;
-  }
-
   ensure_face_ready (f, 1);
-  {
-    XGCValues gcv;
-    struct face *face = FRAME_FACES (f) [1];
-
-    XGetGCValues (x_current_display, f->display.x->reverse_gc,
-                 GCForeground | GCBackground | GCFont, &gcv);
-    face->gc         = f->display.x->reverse_gc;
-    face->foreground = gcv.foreground;
-    face->background = gcv.background;
-    face->font       = f->display.x->font;
-    face->stipple = 0;
-    face->underline = 0;
-  }
+
+  recompute_basic_faces (f);
 }
 
+
 /* Called from Fdelete_frame.  */
 void
 free_frame_faces (f)
@@ -481,34 +462,39 @@ free_frame_faces (f)
   Display *dpy = x_current_display;
   int i;
 
-  /* The first two faces on the frame are just made of resources which 
-     we borrowed from the frame's GC's, so don't free them.  Let
-     them get freed by the x_destroy_window code.  */
-  for (i = 2; i < FRAME_N_FACES (f); i++)
+  BLOCK_INPUT;
+
+  for (i = 0; i < FRAME_N_FACES (f); i++)
     {
       struct face *face = FRAME_FACES (f) [i];
-      if (! face)
-        continue;
-      if (face->gc)
-       XFreeGC (dpy, face->gc);
-      unload_font (f, face->font);
-      unload_color (f, face->foreground);
-      unload_color (f, face->background);
+      if (face)
+       {
+         if (face->gc)
+           XFreeGC (dpy, face->gc);
+         if (! face->copy)
+           {
+             unload_font (f, face->font);
+             unload_color (f, face->foreground);
+             unload_color (f, face->background);
 #if 0
-      unload_pixmap (f, face->stipple);
+             unload_pixmap (f, face->stipple);
 #endif
-      xfree (face);
+           }
+         xfree (face);
+       }
     }
   xfree (FRAME_FACES (f));
   FRAME_FACES (f) = 0;
   FRAME_N_FACES (f) = 0;
+
+  UNBLOCK_INPUT;
 }
 \f
 /* Interning faces in a frame's face array.  */
 
 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
    find one.  */
-int
+static int
 intern_frame_face (frame, new_face)
      struct frame *frame;
      struct face *new_face;
@@ -530,6 +516,7 @@ intern_frame_face (frame, new_face)
 
   ensure_face_ready (frame, i);
   bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face));
+  FRAME_FACES (frame)[i]->copy = 1;
 
   return i;
 }
@@ -564,6 +551,20 @@ ensure_face_ready (f, id)
 \f
 /* Computing faces appropriate for a given piece of text in a buffer.  */
 
+/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
+   We assume that they're both character-cell fonts.  */
+int
+same_size_fonts (font1, font2)
+     XFontStruct *font1, *font2;
+{
+  XCharStruct *bounds1 = &font1->min_bounds;
+  XCharStruct *bounds2 = &font2->min_bounds;
+
+  return (bounds1->width == bounds2->width
+         && bounds1->ascent == bounds2->ascent
+         && bounds1->descent == bounds2->descent);
+}
+
 /* Modify face TO by copying from FROM all properties which have
    nondefault settings.  */
 static void 
@@ -584,6 +585,23 @@ merge_faces (from, to)
     to->underline = from->underline;
 }
 
+/* Set up the basic set of facial parameters, based on the frame's
+   data; all faces are deltas applied to this.  */
+static void
+compute_base_face (f, face)
+     FRAME_PTR f;
+     struct face *face;
+{
+  struct x_display *d = f->display.x;
+  
+  face->gc = 0;
+  face->foreground = d->foreground_pixel;
+  face->background = d->background_pixel;
+  face->font = d->font;
+  face->underline = 0;
+}
+
+
 struct sortvec
 {
   Lisp_Object overlay;
@@ -680,8 +698,7 @@ compute_char_face (f, w, pos, region_beg, region_end, endptr)
       && !(pos >= region_beg && pos < region_end))
     return 0;
 
-  bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face));
-  face.gc = 0;
+  compute_base_face (f, &face);
 
   if (!NILP (prop))
     {
@@ -777,8 +794,7 @@ compute_glyph_face (f, face_code)
 {
   struct face face;
 
-  bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (face));
-  face.gc = 0;
+  compute_base_face (f, &face);
 
   if (face_code >= 0 && face_code < FRAME_N_FACES (f)
       && FRAME_FACES (f) [face_code] != 0)
@@ -786,6 +802,34 @@ compute_glyph_face (f, face_code)
 
   return intern_frame_face (f, &face);
 }
+
+
+/* Recompute the GC's for the default and modeline faces.
+   We call this after changing frame parameters on which those GC's
+   depend.  */
+void
+recompute_basic_faces (f)
+     FRAME_PTR f;
+{
+  /* If the frame's faces haven't been initialized yet, don't worry about
+     this stuff.  */
+  if (FRAME_N_FACES (f) < 2)
+    return;
+
+  BLOCK_INPUT;
+
+  if (FRAME_DEFAULT_FACE (f)->gc)
+    XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
+  build_face (f, FRAME_DEFAULT_FACE (f));
+
+  if (FRAME_MODE_LINE_FACE (f)->gc)
+    XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
+  build_face (f, FRAME_MODE_LINE_FACE (f));
+
+  UNBLOCK_INPUT;
+}
+
+
 \f
 /* Lisp interface. */
 
@@ -900,9 +944,7 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
   if (id == 0)
     {
       BLOCK_INPUT;
-      if (FRAME_DEFAULT_FACE (f)->gc != 0
-         && FRAME_DEFAULT_FACE (f)->gc != f->display.x->normal_gc
-         && FRAME_DEFAULT_FACE (f)->gc != f->display.x->reverse_gc)
+      if (FRAME_DEFAULT_FACE (f)->gc != 0)
        XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
       build_face (f, FRAME_DEFAULT_FACE (f));
       UNBLOCK_INPUT;
@@ -911,9 +953,7 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
   if (id == 1)
     {
       BLOCK_INPUT;
-      if (FRAME_MODE_LINE_FACE (f)->gc != 0
-         && FRAME_MODE_LINE_FACE (f)->gc != f->display.x->normal_gc
-         && FRAME_MODE_LINE_FACE (f)->gc != f->display.x->reverse_gc)
+      if (FRAME_MODE_LINE_FACE (f)->gc != 0)
        XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
       build_face (f, FRAME_MODE_LINE_FACE (f));
       UNBLOCK_INPUT;